package com.gomoku.controller;

import com.gomoku.model.Board;
import com.gomoku.model.GameState;
import com.gomoku.model.Move;
import com.gomoku.service.AIService;
import com.gomoku.service.AIService_MCTS;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@RestController
@RequestMapping("/api/game")
public class GameController {

    @Autowired
    private AIService aiService;
    @Autowired
    private AIService_MCTS aiServiceMcts;

    // 存储每个 sessionID 对应的棋盘
    private static final ConcurrentHashMap<String, Board> userBoards = new ConcurrentHashMap<>();
    private static final ConcurrentHashMap<String, GameState> gameStates = new ConcurrentHashMap<>();
    private static final ConcurrentHashMap<String, Boolean> isPlayerTurnMap = new ConcurrentHashMap<>();
    private static final ConcurrentHashMap<String, Integer> aiModelChoices = new ConcurrentHashMap<>();
    private static final ConcurrentHashMap<String, Integer> difficulties = new ConcurrentHashMap<>();

    // 获取当前会话的棋盘
    private Board getBoardForSession(String sessionId) {
        return userBoards.get(sessionId);
    }


    // 获取当前会话的游戏状态
    private GameState getGameStateForSession(String sessionId) {
        return gameStates.get(sessionId);
    }

    // 获取当前会话是否是玩家的回合
    private Boolean isPlayerTurnForSession(String sessionId) {
        return isPlayerTurnMap.get(sessionId);
    }

    @PostMapping("/start1")
    public ResponseEntity<?> startGame2(@RequestParam(defaultValue = "true") boolean playerFirst,
                                        @RequestParam(defaultValue = "2") int difficulty,
                                        @RequestParam(defaultValue = "1") int aiModel) {
        try {
            String sessionId = java.util.UUID.randomUUID().toString();  // 为每个用户生成独立的 sessionID
           // log.info("session:{}1111111111", sessionId);
            Board board = new Board();
            GameState gameState = GameState.IN_PROGRESS;

            // 初始化会话中的信息
            userBoards.put(sessionId, board);
            gameStates.put(sessionId, gameState);
            isPlayerTurnMap.put(sessionId, playerFirst);


            return ResponseEntity.ok(new GameResponse(board, gameState, isPlayerTurnMap.get(sessionId), sessionId));

        } catch (Exception e) {
            log.error("游戏初始化失败", e);
            return ResponseEntity.badRequest().body("Error starting game: " + e.getMessage());
        }
    }

    @PostMapping("/start")
    public ResponseEntity<?> startGame(@RequestParam(defaultValue = "true") boolean playerFirst,
                                       @RequestParam(defaultValue = "2") int difficulty,
                                       @RequestParam(defaultValue = "1") int aiModel,
                                       @RequestParam String sessionId) {
        try {
            //log.info("session:{}1111111111", sessionId);
            Board board = new Board();
            GameState gameState = GameState.IN_PROGRESS;

            // 初始化会话中的信息
            userBoards.put(sessionId, board);
            gameStates.put(sessionId, gameState);
            isPlayerTurnMap.put(sessionId, playerFirst);
            aiModelChoices.put(sessionId, aiModel);
            difficulties.put(sessionId, difficulty);

            // AI首次落子
            if (!playerFirst) {
                int centerPos = Board.BOARD_SIZE / 2;
                board.makeMove(centerPos, centerPos, true);
                //System.out.println("board:  "+board);
                isPlayerTurnMap.put(sessionId, true);  // 转换到玩家回合
                return ResponseEntity.ok(new GameResponse(board, gameState, isPlayerTurnMap.get(sessionId), sessionId, centerPos, centerPos));
            }

            return ResponseEntity.ok(new GameResponse(board, gameState, isPlayerTurnMap.get(sessionId), sessionId));

        } catch (Exception e) {
            log.error("游戏初始化失败", e);
            return ResponseEntity.badRequest().body("Error starting game: " + e.getMessage());
        }
    }

    /**
     * 调用AI计算棋子步数 返回坐标
     * @param moveRequest
     * @return
     */
    @PostMapping("/move")
    public ResponseEntity<?> makeMove(@RequestBody MoveRequest moveRequest) {

        try {

            String sessionId = moveRequest.getSessionId();
            // 处理逻辑
           // System.out.println("Received sessionId:11111111111111 " + sessionId);
            Board board = getBoardForSession(sessionId);
            GameState gameState = getGameStateForSession(sessionId);
            Boolean isPlayerTurn = isPlayerTurnForSession(sessionId);
            int aiModelChoice = aiModelChoices.get(sessionId);
            int difficulty = difficulties.get(sessionId);

            if (board == null || gameState != GameState.IN_PROGRESS || !isPlayerTurn) {
                return ResponseEntity.badRequest().body("Invalid move or game state");
            }

            int row = moveRequest.getRow();
            int col = moveRequest.getCol();

            if (!board.isValidMove(row, col)) {
                return ResponseEntity.badRequest().body("Invalid move position");
            }

            // 玩家下棋
            board.makeMove(row, col, false);
            if (board.checkWin(row, col)) {
                gameState = GameState.PLAYER_WIN;
                gameStates.put(sessionId, gameState);
                return ResponseEntity.ok(new GameResponse(board, gameState, isPlayerTurn, sessionId));
            }

            if (board.isFull()) {
                gameState = GameState.DRAW;
                gameStates.put(sessionId, gameState);
                return ResponseEntity.ok(new GameResponse(board, gameState, isPlayerTurn, sessionId));
            }

            // AI回合
            isPlayerTurnMap.put(sessionId, false);
            Move aiMove = new Move();
            if (aiModelChoice == 1) {
                aiService.setMaxDepth(difficulty);
                aiMove = aiService.calculateNextMove(board);
            } else {
                aiServiceMcts.setDifficulty(difficulty);
                aiMove = aiServiceMcts.calculateNextMove(board);
            }

            board.makeMove(aiMove.getRow(), aiMove.getCol(), true);

            if (board.checkWin(aiMove.getRow(), aiMove.getCol())) {
                gameState = GameState.AI_WIN;
                gameStates.put(sessionId, gameState);
                return ResponseEntity.ok(new GameResponse(board, gameState, isPlayerTurn, sessionId, aiMove.getRow(), aiMove.getCol()));
            }

            if (board.isFull()) {
                gameState = GameState.DRAW;
                gameStates.put(sessionId, gameState);
                return ResponseEntity.ok(new GameResponse(board, gameState, isPlayerTurn, sessionId, aiMove.getRow(), aiMove.getCol()));
            }

            // AI下完后轮到玩家
            isPlayerTurnMap.put(sessionId, true);
            return ResponseEntity.ok(new GameResponse(board, gameState, isPlayerTurn, sessionId, aiMove.getRow(), aiMove.getCol()));

        } catch (Exception e) {
            return ResponseEntity.badRequest().body("Error processing move: " + e.getMessage());
        }
    }

    @PostMapping("/update")
    public ResponseEntity<?> updateBoard(@RequestBody BoardUpdateRequest request) {
        Board updatedBoard = request.getBoard();
        String sessionId = request.getSessionId();

        if (updatedBoard == null) {
            return ResponseEntity.badRequest().body("无效的棋盘状态");
        }

        userBoards.put(sessionId, updatedBoard);  // 使用 sessionId 保存棋盘状态
        //System.out.println("upda:" + updatedBoard);

        // 获取当前会话的棋盘、游戏状态和当前回合
        Board board = getBoardForSession(sessionId);
        GameState gameState = getGameStateForSession(sessionId);
        Boolean isPlayerTurn = isPlayerTurnForSession(sessionId);

        // 返回更新后的棋盘状态
        return ResponseEntity.ok(new GameResponse(board, gameState, isPlayerTurn, sessionId));
    }

    /**
     * 棋子移动信息
     */
    public static class MoveRequest {
        private int row;
        private int col;

        private String sessionId;

        public void setSessionId(String sessionId) {
            this.sessionId = sessionId;
        }

        public String getSessionId() {
            return sessionId;
        }

        public int getRow() { return row; }
        public void setRow(int row) { this.row = row; }
        public int getCol() { return col; }
        public void setCol(int col) { this.col = col; }
    }


    public static class BoardUpdateRequest {
        private Board board;
        private String sessionId;

        // Getter 和 Setter
        public Board getBoard() {
            return board;
        }

        public void setBoard(Board board) {
            this.board = board;
        }

        public String getSessionId() {
            return sessionId;
        }

        public void setSessionId(String sessionId) {
            this.sessionId = sessionId;
        }
    }


    /**
     * 返回前端信息
     */
    public static class GameResponse {
        private final Board board;
        private final GameState gameState;
        private final boolean playerTurn;
        private final String sessionId;
        private int currentX;
        private int currentY;

        public GameResponse(Board board, GameState gameState, boolean isPlayerTurn, String sessionId){
            this.board = board;
            this.gameState = gameState;
            this.playerTurn = isPlayerTurn;
            this.sessionId = sessionId;

        }

        public GameResponse(Board board, GameState gameState, boolean isPlayerTurn, String sessionId, int x, int y) {
            this.board = board;
            this.gameState = gameState;
            this.playerTurn = isPlayerTurn;
            this.sessionId = sessionId;
            this.currentX=x;
            this.currentY=y;
        }

        public Board getBoard() { return board; }
        public GameState getGameState() { return gameState; }
        public boolean isPlayerTurn() { return playerTurn; }
        public int getCurrentX(){return currentX;}
        public int getCurrentY(){return currentY;}

        public String getSessionId() {
            return sessionId;
        }
    }
} 